<template>
  <div class="worktable-stats">
    <div id="graph-container-wrapper">
      <div id="graph-container"></div>
    </div>
    <div id="minimap-container"></div>
  </div>
</template>

<script>
import {Graph} from "@antv/x6";
import { DagreLayout } from "@antv/layout"

import "./nodes/registerNode";

import "./edges/registerEdge";

export default {
  props: {
    processDetail: Object
  },

  watch: {
    processDetail: {
      handler() {
        this.getCanvasData()
      },
      deep: true
    },
  },

  // 提供全局公共数据
  provide() {
    return {
      worktableContext: this,
      graph: this.graph,
    }
  },

  mounted() {
    this.initGraph()
    this.getCanvasData()
    this.bindResizeEvent()
  },

  beforeUnmount() {
    window.removeEventListener('resize', this.thatResize)
    clearTimeout(this.resizeDelayTimer)
    this.graph.dispose()
  },

  methods: {
    initGraph() {
      const that = this
      const graph = new Graph({
        container: document.getElementById("graph-container"),
        mousewheel: {
          enabled: true,
          zoomAtMousePosition: true,
          modifiers: "ctrl",
          minScale: 0.5,
          maxScale: 3,
        },
        connecting: {
          connector: {
            name: 'smooth',
            args: {
              direction: 'V'
            }
          },
          allowBlank: false,
          allowLoop: false,
        },
        interacting: {
          nodeMovable: false,
          edgeMovable: false,
        },
        panning: false,
        minimap: {
          enabled: true,
          container: document.getElementById("minimap-container"),
        },
        scroller: {
          enabled: true,
          padding: 50,
        },
      });

      graph.on('node:click', (e) => {
        that.$emit('node-click', e)
      })

      this.graph = graph;
    },

    getCanvasData() {
      const { canvas, nodes, edges, events} = this.processDetail

      this.canvasData = canvas;
      this.events = events;

      // 清除原有路径点 由本组件控制
      let _edges = edges.map(edge => ({...edge, vertices: []}))

      // 修改为数据卡片节点
      let _nodes = nodes.map(node => ({
        ...node,
        shape: 'data-card',
        data: {
          ...node.data,
          originShape: node.shape
        },
        size: { // 和注册时的大小保持一致
          width: 300,
          height: 140
        },
        ports: undefined
      }))

      // 布局文档
      // https://g6.antv.vision/zh/examples/net/dagreFlow#basicDagre
      // https://x6.antv.vision/zh/docs/tutorial/advanced/layout#dagre
      const dagreLayout = new DagreLayout({
        type: 'dagre',
        nodesep: 20,
        ranksep: 20,
      })

      let layoutModel = {
        nodes: _nodes,
        edges: _edges,
      }

      layoutModel = dagreLayout.layout(layoutModel)

      // 布局算法返回的 x、y 是节点的中心点坐标，在 X6 中，节点的 x、y 其实是左上角坐标，所以布局之后，需要做一次坐标转换
      layoutModel.nodes.forEach(node => {
        node.x -= node.size.width / 2;
        node.y -= node.size.height / 2;
      })


      this.graph.fromJSON(layoutModel);

      const startCellModel = nodes.find(item => item.shape === 'start')
      if (startCellModel) {
        const startCell = this.graph.getCellById(startCellModel.id)
        this.graph.positionCell(startCell, 'top', {
          padding: {
            top: 20
          }
        })
      } else {
        this.graph.positionContent('top', {
          padding: {
            top: 20
          }
        })
      }

      // 不显示placeholder
      const placeholderNodeIds = nodes.filter(node => node.shape === 'placeholder').map(node => node.id)

      placeholderNodeIds.forEach(nodeId => {
        this.graph.removeCell(nodeId)
      })


      this.graph.centerContent()
    },

    bindResizeEvent() {
      this.thatResize = this.resize.bind(this)
      window.addEventListener('resize', this.thatResize)
    },

    resize() {
      clearTimeout(this.resizeDelayTimer)
      this.resizeDelayTimer = setTimeout(() => {
        const containerWrapperRect = document.querySelector('#graph-container-wrapper').getBoundingClientRect()
        this.graph.resize(containerWrapperRect.width, containerWrapperRect.height)
      }, 1000)
    },
  }
}
</script>

<style scoped lang="scss">

.worktable-stats {
  //width: 100%;
  height: 750px;
  position: relative;
  //background: white;

  #graph-container-wrapper {
    width: 100%;
    height: 100%;

    #graph-container {
      width: 100%;
      height: 100%;
    }
  }
}

#minimap-container {
  position: absolute;
  top: 10px;
  right: 10px;
  box-shadow: 5px 5px 5px 0 rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  overflow: hidden;
}
</style>
